package com.engine4cloud.tdf.supervision.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.common.core.constant.enums.SpecialCrimeTypeEnum;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.supervision.convert.JzdxSpecialCrimeConvert;
import com.engine4cloud.tdf.supervision.dto.query.JzdxSpecialCrimeQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxSpecialCrimeResultDTO;
import com.engine4cloud.tdf.supervision.dto.update.JzdxJudgmentUpdateDTO;
import com.engine4cloud.tdf.supervision.entity.JzdxJudgmentEntity;
import com.engine4cloud.tdf.supervision.entity.JzdxSpecialCrimeEntity;
import com.engine4cloud.tdf.supervision.mapper.JzdxSpecialCrimeMapper;
import com.engine4cloud.tdf.supervision.service.JzdxSpecialCrimeService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 矫正对象特殊罪行信息
 *
 * @author wenjie
 * @date 2024-03-15 15:08:35
 */
@Service
public class JzdxSpecialCrimeServiceImpl extends ServiceImpl<JzdxSpecialCrimeMapper, JzdxSpecialCrimeEntity> implements JzdxSpecialCrimeService {
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateBatch(JzdxJudgmentEntity entity, JzdxJudgmentUpdateDTO dto) {
        JzdxSpecialCrimeQueryDTO query = new JzdxSpecialCrimeQueryDTO();
        query.setRybh(entity.getRybh());
        List<JzdxSpecialCrimeEntity> existedList = super.list(wrapper(query));

        List<JzdxSpecialCrimeEntity> preSaveSpecialCrimeList = this.preSaveSpecialCrimeList(entity, existedList, dto);
        if (CollectionUtils.isNotEmpty(preSaveSpecialCrimeList)) {
            this.saveBatch(preSaveSpecialCrimeList);
        }

        List<Long> preDeleteSpecialCrimeList = this.preDeleteSpecialCrimeList(existedList, dto);
        if (CollectionUtils.isNotEmpty(preDeleteSpecialCrimeList)) {
            this.removeBatchByIds(preDeleteSpecialCrimeList);
        }

        return true;
    }

    @Override
    public List<JzdxSpecialCrimeResultDTO> find(JzdxSpecialCrimeQueryDTO query) {
        return super.list(wrapper(query)).stream().map(JzdxSpecialCrimeConvert.INSTANCE::convert).toList();
    }

    private List<JzdxSpecialCrimeEntity> preSaveSpecialCrimeList(JzdxJudgmentEntity entity, List<JzdxSpecialCrimeEntity> existedList, JzdxJudgmentUpdateDTO dto) {
        List<JzdxSpecialCrimeEntity> preSaveSpecialCrimeList = new ArrayList<>();

        //五独
        Map<String, JzdxSpecialCrimeEntity> existedFiveIndependenceMap = existedList.stream().filter(crime -> Objects.equals(SpecialCrimeTypeEnum.FIVE_INDEPENDENCE, crime.getTszxlx()))
                .collect(Collectors.toMap(JzdxSpecialCrimeEntity::getJtlx, Function.identity(), (v1, v2) -> v1));
        //五涉
        Map<String, JzdxSpecialCrimeEntity> existedFiveInvolvementMap = existedList.stream().filter(crime -> Objects.equals(SpecialCrimeTypeEnum.FIVE_INVOLVEMENT, crime.getTszxlx()))
                .collect(Collectors.toMap(JzdxSpecialCrimeEntity::getJtlx, Function.identity(), (v1, v2) -> v1));
        //四史
        Map<String, JzdxSpecialCrimeEntity> existedFourHistoryMap = existedList.stream().filter(crime -> Objects.equals(SpecialCrimeTypeEnum.FOUR_HISTORY, crime.getTszxlx()))
                .collect(Collectors.toMap(JzdxSpecialCrimeEntity::getJtlx, Function.identity(), (v1, v2) -> v1));

        dto.getFiveIndependenceList().forEach(crime -> {
            if (!existedFiveIndependenceMap.containsKey(crime)) {
                preSaveSpecialCrimeList.add(JzdxSpecialCrimeConvert.INSTANCE.convert(entity.getRybh(), SpecialCrimeTypeEnum.FIVE_INDEPENDENCE, crime, entity.getTenantId()));
            }
        });

        dto.getFiveInvolvementList().forEach(crime -> {
            if (!existedFiveInvolvementMap.containsKey(crime)) {
                preSaveSpecialCrimeList.add(JzdxSpecialCrimeConvert.INSTANCE.convert(entity.getRybh(), SpecialCrimeTypeEnum.FIVE_INVOLVEMENT, crime, entity.getTenantId()));
            }
        });

        dto.getFourHistoryList().forEach(crime -> {
            if (!existedFourHistoryMap.containsKey(crime)) {
                preSaveSpecialCrimeList.add(JzdxSpecialCrimeConvert.INSTANCE.convert(entity.getRybh(), SpecialCrimeTypeEnum.FOUR_HISTORY, crime, entity.getTenantId()));
            }
        });

        return preSaveSpecialCrimeList;
    }

    private List<Long> preDeleteSpecialCrimeList(List<JzdxSpecialCrimeEntity> existedList, JzdxJudgmentUpdateDTO dto) {
        List<Long> preDeleteSpecialCrimeList = new ArrayList<>();
        //五独
        List<JzdxSpecialCrimeEntity> existedFiveIndependenceList = existedList.stream().filter(crime -> Objects.equals(SpecialCrimeTypeEnum.FIVE_INDEPENDENCE, crime.getTszxlx())).toList();
        //五涉
        List<JzdxSpecialCrimeEntity> existedFiveInvolvementList = existedList.stream().filter(crime -> Objects.equals(SpecialCrimeTypeEnum.FIVE_INVOLVEMENT, crime.getTszxlx())).toList();
        //四史
        List<JzdxSpecialCrimeEntity> existedFourHistoryList = existedList.stream().filter(crime -> Objects.equals(SpecialCrimeTypeEnum.FOUR_HISTORY, crime.getTszxlx())).toList();

        List<Long> preDeleteFiveIndependenceList = existedFiveIndependenceList.stream().filter(crime -> !dto.getFiveIndependenceList().contains(crime.getJtlx())).map(JzdxSpecialCrimeEntity::getId).toList();
        List<Long> preDeleteFiveInvolvementList = existedFiveInvolvementList.stream().filter(crime -> !dto.getFiveInvolvementList().contains(crime.getJtlx())).map(JzdxSpecialCrimeEntity::getId).toList();
        List<Long> preDeleteFourHistoryList = existedFourHistoryList.stream().filter(crime -> !dto.getFourHistoryList().contains(crime.getJtlx())).map(JzdxSpecialCrimeEntity::getId).toList();

        if (CollectionUtils.isNotEmpty(preDeleteFiveIndependenceList)) {
            preDeleteSpecialCrimeList.addAll(preDeleteFiveIndependenceList);
        }

        if (CollectionUtils.isNotEmpty(preDeleteFiveInvolvementList)) {
            preDeleteSpecialCrimeList.addAll(preDeleteFiveInvolvementList);
        }

        if (CollectionUtils.isNotEmpty(preDeleteFourHistoryList)) {
            preDeleteSpecialCrimeList.addAll(preDeleteFourHistoryList);
        }

        return preDeleteSpecialCrimeList;
    }

    private LambdaQueryWrapper<JzdxSpecialCrimeEntity> wrapper(JzdxSpecialCrimeQueryDTO query) {
        LambdaQueryWrapper<JzdxSpecialCrimeEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(JzdxSpecialCrimeEntity::getId, v));
        Queries.accept(query.getRybh(), v -> wrapper.eq(JzdxSpecialCrimeEntity::getRybh, v));
        return wrapper;
    }
}